home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / FinderFlocks / FlockUtils.cp < prev    next >
Text File  |  1996-06-22  |  14KB  |  559 lines

  1. #include "CFlock.h"
  2. #include "FlockDrawing.h"
  3. #include <stdio.h>
  4.  
  5. // a sick hack for key control of the flock
  6. extern ControlRec            gCurrentControls;
  7. extern Boolean                gControlsChanged;
  8.  
  9. short
  10. abs(short i)
  11. {
  12.     if (i < 0)
  13.         return(-i);
  14.     return(i);
  15. }
  16.  
  17. /* long
  18. labs(long i)
  19. {
  20.     if (i < 0)
  21.         return(-i);
  22.     return(i);
  23. } */
  24.  
  25. /* This routine replaces the given string with a string from the resource file, and also
  26. returns it */ 
  27. /* char* TheStr(Str255 str, short index)
  28. {
  29.     GetIndString(str, kFlockStringsID, index);
  30.     return &str;
  31. } */
  32.  
  33. // This routine averages the two vectors, and returns the result in a
  34. void TwoVecAvg(FloatPoint *a, FloatPoint *b)
  35. {
  36.     a->h = (a->h + b->h) / 2;
  37.     a->v = (a->v + b->v) / 2;
  38. }
  39.  
  40. double VecMagSq(double h, double v)
  41. {
  42.     double hsq, vsq;
  43.     
  44.     hsq = h * h;
  45.     vsq = v * v;
  46.     return (hsq + vsq);
  47. }
  48.  
  49. void    Clamp(FloatPoint *vec, double max)
  50. {
  51.     double    theMax = max;
  52.     double    biggest;
  53.     double    absh, absv;
  54.     
  55.     absh = fabs(vec->h);
  56.     absv = fabs(vec->v);
  57.     biggest = (absv > absh) ? absv : absh;
  58.     if(biggest <= max)
  59.         return;
  60.     vec->h = (vec->h * max) / biggest;
  61.     vec->v = (vec->v * max) / biggest;
  62. }
  63.  
  64.  
  65. /* Some QuickDraw Utils */
  66.  
  67.  
  68. //    This routine builds a new PixMap or Bitmap to the given specs. It simply clones 
  69. //    the current GDevice's PixMap, then resizes it. It does NOT allocate space for
  70. //  the image itself, but returns the required size in bytes. Returns nil on error.
  71. //  Assumes that the current device is the right one
  72.  
  73. long BuildMap(Handle *aMap, Rect *aRect, short theDepth)
  74. {
  75.     long                rowbytes, bitsSize;
  76.     Handle                localMap;
  77.     
  78.     // If theDepth is 1, then we have either B&W QD or ColorQD in 1 bit. 
  79.     // In either case use a BitMap, not a PixMap.
  80.     if(theDepth == 1)
  81.     {
  82.         // Allocate space for the BitMap
  83.         localMap = NewHandle(sizeof(BitMap));
  84.         if(localMap == nil)
  85.             return 0;
  86.         
  87.         // Resize the new map to the rect
  88.         bitsSize = SizeBitMap((BitMap *)*localMap, aRect);
  89.     }
  90.     else     // a full-fledged PixMap, Color QD better be available...
  91.     {
  92.         GDHandle    mapDevice;
  93.         
  94.         // Get the current device
  95.         mapDevice = GetGDevice();
  96.         if(mapDevice == nil)
  97.             return 0;
  98.         
  99.         // Allocate space for the PixMap
  100.         localMap = (Handle)NewPixMap();
  101.         if(localMap == nil)
  102.             return 0;
  103.         
  104.         // Clone the device's PixMap, including color table
  105.         CopyPixMap((*mapDevice)->gdPMap, (PixMapHandle)localMap);
  106.         
  107.         // Resize the new map to the rect
  108.         bitsSize = SizePixMap((PixMapHandle)localMap, aRect);
  109.     }
  110.     // Cool, we made it. Install the new map and return size of image
  111.     *aMap = localMap;
  112.     return bitsSize;
  113. }
  114.  
  115. // Changes rowBytes and bounds of the given PixMap so that it corresponds to the given rect    
  116. long SizePixMap(PixMapHandle ThePix, Rect *TheRect)
  117. {
  118.     long    rb, ptrsize;
  119.     
  120.     rb    =    ((((**ThePix).pixelSize * (TheRect->right - TheRect->left)) + 15) / 16) * 2;
  121.     ptrsize = rb * (TheRect->bottom - TheRect->top);
  122.     (**ThePix).rowBytes = rb | 0x8000;
  123.     (**ThePix).bounds = *TheRect;
  124.     return ptrsize;
  125. }
  126.     
  127. // Changes rowBytes and bounds of the given BitMap so that it corresponds to the given rect    
  128. long SizeBitMap(BitMap *TheMap, Rect *TheRect)
  129. {
  130.     long    rb, ptrsize;
  131.     
  132.     rb = ((TheRect->right - TheRect->left + 15) / 16) * 2;
  133.     ptrsize = rb * (TheRect->bottom - TheRect->top);
  134.     TheMap->rowBytes = rb;
  135.     TheMap->bounds = *TheRect;
  136.     return ptrsize;
  137. }
  138.  
  139. // A key was hit: if it's a flock control do something
  140. /*
  141.             0x1E, // up and down arrows : flock size
  142.             0x1F,
  143.  
  144.             0x1C, // left and right arrows: flock type
  145.             0x1D,
  146.  
  147.             0x31, // 1, q: comfy distance
  148.             0x71,
  149.             
  150.             0x32, // 2, w: vision limit
  151.             0x77,
  152.             
  153.             0x34, // 4, r: Max Avoid Urge
  154.             0x72,
  155.  
  156.             0x35, // 5, t: Max match Urge
  157.             0x74,
  158.  
  159.             0x36, // 6, y: Max Centering Urge
  160.             0x79,
  161.  
  162.             0x38, // 8, i: max Oomph
  163.             0x69,
  164.  
  165.             0x39, // 9, o: Max Accel
  166.             0x6F,
  167.  
  168.             0x30, // 0, p: Max Velocity
  169.             0x70,
  170. */
  171. void FlockControlKey(char key)
  172. {
  173.     switch(key)
  174.     {
  175.         // up and down arrows affect flock size
  176.         case 0x1E:
  177.             //gCurrentControls.fNumBoidsCtl += 10;
  178.             gControlsChanged = true;
  179.             break;
  180.         case 0x1F:
  181.             //gCurrentControls.fNumBoidsCtl -= 10;
  182.             gControlsChanged = true;
  183.             break;
  184.             
  185.         // left and right arrows affect flock type
  186.         case 0x1C:
  187.             gCurrentControls.fBoidTypeCtl -= 1;
  188.             gControlsChanged = true;
  189.             break;
  190.         case 0x1D:
  191.             gCurrentControls.fBoidTypeCtl += 1;
  192.             gControlsChanged = true;
  193.             break;
  194.         
  195.         // 1 and q affect comfy dist
  196.         case 0x31:
  197.             gCurrentControls.fComfyDistCtl += 1;
  198.             gControlsChanged = true;
  199.             break;
  200.         case 0x71:
  201.             gCurrentControls.fComfyDistCtl -= 1;
  202.             gControlsChanged = true;
  203.             break;
  204.  
  205.         // 2 and w affect vision limit
  206.         case 0x32:
  207.             gCurrentControls.fAwareDistCtl += 1;
  208.             gControlsChanged = true;
  209.             break;
  210.         case 0x77:
  211.             gCurrentControls.fAwareDistCtl -= 1;
  212.             gControlsChanged = true;
  213.             break;
  214.  
  215.         // 4 and r affect max avoidance urge
  216.         case 0x34:
  217.             gCurrentControls.fAvoidMaxCtl += 1;
  218.             gControlsChanged = true;
  219.             break;
  220.         case 0x72:
  221.             gCurrentControls.fAvoidMaxCtl -= 1;
  222.             gControlsChanged = true;
  223.             break;
  224.  
  225.         // 5 and t affect max matching urge
  226.         case 0x35:
  227.             gCurrentControls.fMatchMaxCtl += 1;
  228.             gControlsChanged = true;
  229.             break;
  230.         case 0x74:
  231.             gCurrentControls.fMatchMaxCtl -= 1;
  232.             gControlsChanged = true;
  233.             break;
  234.  
  235.         // 6 and y affect max centering urge
  236.         case 0x36:
  237.             gCurrentControls.fCenterMaxCtl += 1;
  238.             gControlsChanged = true;
  239.             break;
  240.         case 0x79:
  241.             gCurrentControls.fCenterMaxCtl -= 1;
  242.             gControlsChanged = true;
  243.             break;
  244.  
  245.         // 8 and i affect max oomph available
  246.         case 0x38:
  247.             gCurrentControls.fMaxEffortCtl += 1;
  248.             gControlsChanged = true;
  249.             break;
  250.         case 0x69:
  251.             gCurrentControls.fMaxEffortCtl -= 1;
  252.             gControlsChanged = true;
  253.             break;
  254.  
  255.         // 9 and o affect max acceleration
  256.         case 0x39:
  257.             gCurrentControls.fMaxAccelCtl += 1;
  258.             gControlsChanged = true;
  259.             break;
  260.         case 0x6F:
  261.             gCurrentControls.fMaxAccelCtl -= 1;
  262.             gControlsChanged = true;
  263.             break;
  264.  
  265.         // 0 and p affect max velocity
  266.         case 0x30:
  267.             gCurrentControls.fMaxVelocityCtl += 1;
  268.             gControlsChanged = true;
  269.             break;
  270.         case 0x70:
  271.             gCurrentControls.fMaxVelocityCtl -= 1;
  272.             gControlsChanged = true;
  273.             break;
  274.  
  275.     }
  276. }
  277.         
  278. /* Sets the given control block to the values in the appropriate resource, but 
  279. preserves fNumBoidsCtl and fBoidTypeCtl */
  280. void    GetNewControls(ControlRec *controls, long type)
  281. {
  282.     Handle        hVals = nil;
  283.     short        num1, num2;
  284.     
  285.     num1 = controls->fNumBoidsCtl;
  286.     num2 = controls->fBoidTypeCtl;
  287.  
  288.     /* Get the default control values */
  289.     hVals = GetResource('FCTL', type + kIDOffset);
  290.     if(hVals != nil)
  291.     {
  292.         ShortControlRec    shorts;
  293.         
  294.         shorts = *(ShortControlRec *)(*hVals);
  295.         
  296.         // convert to internal longs and doubles
  297.         controls->fNumBoidsCtl = shorts.fNumBoidsCtl;
  298.         controls->fBoidTypeCtl = shorts.fBoidTypeCtl;
  299.         controls->fComfyDistCtl = shorts.fComfyDistCtl;
  300.         controls->fAwareDistCtl = shorts.fAwareDistCtl;
  301.         controls->fAvoidMaxCtl = shorts.fAvoidMaxCtl;
  302.         controls->fMatchMaxCtl = shorts.fMatchMaxCtl;
  303.         controls->fCenterMaxCtl = shorts.fCenterMaxCtl;
  304.         controls->fMaxEffortCtl = shorts.fMaxEffortCtl;
  305.         controls->fMaxAccelCtl = shorts.fMaxAccelCtl;
  306.         controls->fMaxVelocityCtl = shorts.fMaxVelocityCtl;
  307.         ReleaseResource(hVals);
  308.     }
  309.     else
  310.     {
  311.         /* Fake it */
  312.         controls->fNumBoidsCtl = 10;
  313.         controls->fBoidTypeCtl = 1;
  314.         controls->fComfyDistCtl = 50;
  315.         controls->fAwareDistCtl = 50;
  316.         controls->fAvoidMaxCtl = 50;
  317.         controls->fMatchMaxCtl = 50;
  318.         controls->fCenterMaxCtl = 50;
  319.         controls->fMaxEffortCtl = 50;
  320.         controls->fMaxAccelCtl = 50;
  321.         controls->fMaxVelocityCtl = 50;
  322.     }
  323.     
  324.     controls->fNumBoidsCtl = num1;
  325.     controls->fBoidTypeCtl = num2;
  326. }
  327.  
  328. /* turns the given raw (0-100) control block into good controls */
  329. /*void    ProcessControls(ControlRec *raw, ControlRec *good)
  330. {
  331.     *good = *raw;
  332.     
  333.     good->fComfyDistCtl *= 4;
  334.     good->fAwareDistCtl *= 8;
  335.     good->fAvoidMaxCtl /= 4;
  336.     good->fMatchMaxCtl /= 4;
  337.     good->fCenterMaxCtl /= 8;
  338.     good->fMaxEffortCtl *= 1;
  339.     good->fMaxAccelCtl /= 4;
  340.     good->fMaxVelocityCtl /= 4;
  341.     good->fNumBoidsCtl *= 10;
  342.     if(good->fNumBoidsCtl > kMaxBoids)
  343.         good->fNumBoidsCtl = kMaxBoids;
  344. }*/
  345.     
  346. /*void SaveControls(ControlRec *controls, long type)
  347. {
  348.     Handle                contrRes;
  349.     ShortControlRec        shorts;
  350.     
  351.     // Save the controls for next time. First get the default control values
  352.     contrRes = GetResource('FCTL', type + kIDOffset);
  353.     if(contrRes == nil)    // No resource, make one
  354.     {
  355.         contrRes = NewHandle(sizeof(ShortControlRec));
  356.         if(contrRes == nil)    // Bummer, not enough memory. So it goes...
  357.             return;
  358.         
  359.         // Make it a resource
  360.         AddResource(contrRes, 'FCTL', type + kIDOffset, "\p");
  361.         if(ResError() != noErr)
  362.         {
  363.             DisposHandle(contrRes);
  364.             return;
  365.         }
  366.     }
  367.  
  368.     // Copy the controls
  369.     shorts.fNumBoidsCtl = controls->fNumBoidsCtl;
  370.     shorts.fBoidTypeCtl = controls->fBoidTypeCtl;
  371.     shorts.fComfyDistCtl = controls->fComfyDistCtl;
  372.     shorts.fAwareDistCtl = controls->fAwareDistCtl;
  373.     shorts.fAvoidMaxCtl = controls->fAvoidMaxCtl;
  374.     shorts.fMatchMaxCtl = controls->fMatchMaxCtl;
  375.     shorts.fCenterMaxCtl = controls->fCenterMaxCtl;
  376.     shorts.fMaxEffortCtl = controls->fMaxEffortCtl;
  377.     shorts.fMaxAccelCtl = controls->fMaxAccelCtl;
  378.     shorts.fMaxVelocityCtl = controls->fMaxVelocityCtl;
  379.  
  380.     *(ShortControlRec *)*contrRes = shorts;
  381.     ChangedResource(contrRes); // make sure it gets written out
  382.     if(ResError() == noErr)
  383.         WriteResource(contrRes); // ignore the potential write error
  384.     ReleaseResource(contrRes);
  385. }*/
  386.  
  387. /*void GetFlockRect(RgnHandle blankRgn, GMParamBlockPtr params, 
  388.                     Rect *flockRect, long *depth, long screenSetting)
  389. {
  390.     Rect    deepRect, bigRect, blankRect;
  391.     short     cnt, numMonitors, deepDepth = 0, bigDepth = 0;
  392.     long    deepArea = 0, bigArea = 0;
  393.     
  394.     blankRect = (**blankRgn).rgnBBox;
  395.     
  396.     //Look at all monitors, then pick which one to use.
  397.     numMonitors = params->monitors->monitorCount;
  398.     for(cnt = 0; cnt < numMonitors; cnt++)
  399.     {
  400.         Rect    thisRect;
  401.         long    thisArea;
  402.         short    thisDepth;
  403.         
  404.         thisRect = params->monitors->monitorList[cnt].bounds;
  405.         // If this monitor intersects the blankRgn, log its depth and area of intersection
  406.         if(SectRect(&thisRect, &blankRect, &thisRect))
  407.         {
  408.             thisArea = (long)(thisRect.right - thisRect.left) *
  409.                         (long)(thisRect.bottom - thisRect.top);
  410.             thisDepth = params->monitors->monitorList[cnt].curDepth;
  411.             
  412.             // log results if they supersede earlier ones
  413.             if(thisDepth > deepDepth)     
  414.             {
  415.                 deepArea = thisArea;    //Log if deeper than the others
  416.                 deepDepth = thisDepth;
  417.                 deepRect = thisRect;
  418.             }
  419.             if(thisArea > bigArea)        //Log if larger than the others
  420.             {
  421.                 bigArea = thisArea;
  422.                 bigDepth = thisDepth;
  423.                 bigRect = thisRect;
  424.             }
  425.         }
  426.     }
  427.     
  428.     //Logged all monitors. Now pick the right one
  429.     if( screenSetting == kAllScr)
  430.     {
  431.         *depth = bigDepth;
  432.         *flockRect = (**blankRgn).rgnBBox;
  433.     }
  434.     else if(screenSetting == kBigScr)
  435.     {
  436.         *depth = bigDepth;
  437.         *flockRect = bigRect;
  438.     }
  439.     else        //  use deepest
  440.     {
  441.         if(deepDepth == bigDepth)
  442.         {
  443.             *depth = bigDepth;
  444.             *flockRect = bigRect;
  445.         }
  446.         else
  447.         {
  448.             *depth = deepDepth;
  449.             *flockRect = deepRect;
  450.         }
  451.     }
  452. } */
  453.  
  454. void DrawControlValues(Rect *screenRect)
  455. {
  456.     char        textBuffer[512];
  457.     long        length;
  458.     RGBColor    theTextColor = {65535, 0, 0}, blackish = {0, 0, 0}, savedColor;
  459.     short        theXPos = 10, theYPos = screenRect->bottom - 160; // (10 controls * 15 pixel line height) + 10 slop
  460.     Rect        invalRect;
  461.     
  462.     // Save the current color
  463.     GetForeColor( &savedColor );
  464.     
  465.     // set up the invalid rect
  466.     invalRect = *screenRect;
  467.     invalRect.right = 250;
  468.     invalRect.top = theYPos - 15;
  469.     RGBForeColor( &blackish );
  470.     PaintRect(&invalRect);
  471.     
  472.     RGBForeColor( &theTextColor );
  473.     // Draw each control's value
  474.     length = sprintf((char *)&textBuffer[1],
  475.         "%ld - Number of boids",
  476.         gCurrentControls.fNumBoidsCtl);
  477.     textBuffer[0] = length;
  478.     MoveTo(theXPos, theYPos );
  479.     DrawString((ConstStr255Param)textBuffer);
  480.     theYPos += 15;
  481.  
  482.     length = sprintf((char *)&textBuffer[1],
  483.         "%ld - Boid type",
  484.         gCurrentControls.fBoidTypeCtl);
  485.     textBuffer[0] = length;
  486.     MoveTo(theXPos, theYPos );
  487.     DrawString((ConstStr255Param)textBuffer);
  488.     theYPos += 15;
  489.  
  490.     length = sprintf((char *)&textBuffer[1],
  491.         "%.2lf - Comfy distance",
  492.         gCurrentControls.fComfyDistCtl);
  493.     textBuffer[0] = length;
  494.     MoveTo(theXPos, theYPos );
  495.     DrawString((ConstStr255Param)textBuffer);
  496.     theYPos += 15;
  497.  
  498.     length = sprintf((char *)&textBuffer[1],
  499.         "%.2lf - Aware distance",
  500.         gCurrentControls.fAwareDistCtl);
  501.     textBuffer[0] = length;
  502.     MoveTo(theXPos, theYPos );
  503.     DrawString((ConstStr255Param)textBuffer);
  504.     theYPos += 15;
  505.  
  506.     length = sprintf((char *)&textBuffer[1],
  507.         "%.2lf - Max. Avoidance",
  508.         gCurrentControls.fAvoidMaxCtl);
  509.     textBuffer[0] = length;
  510.     MoveTo(theXPos, theYPos );
  511.     DrawString((ConstStr255Param)textBuffer);
  512.     theYPos += 15;
  513.  
  514.     length = sprintf((char *)&textBuffer[1],
  515.         "%.2lf - Max. Match",
  516.         gCurrentControls.fMatchMaxCtl);
  517.     textBuffer[0] = length;
  518.     MoveTo(theXPos, theYPos );
  519.     DrawString((ConstStr255Param)textBuffer);
  520.     theYPos += 15;
  521.  
  522.     length = sprintf((char *)&textBuffer[1],
  523.         "%.2lf - Max. Centering",
  524.         gCurrentControls.fCenterMaxCtl);
  525.     textBuffer[0] = length;
  526.     MoveTo(theXPos, theYPos );
  527.     DrawString((ConstStr255Param)textBuffer);
  528.     theYPos += 15;
  529.  
  530.     length = sprintf((char *)&textBuffer[1],
  531.         "%.2lf - Max. Oomph",
  532.         gCurrentControls.fMaxEffortCtl);
  533.     textBuffer[0] = length;
  534.     MoveTo(theXPos, theYPos );
  535.     DrawString((ConstStr255Param)textBuffer);
  536.     theYPos += 15;
  537.  
  538.     length = sprintf((char *)&textBuffer[1],
  539.         "%.2lf - Max. Acceleration",
  540.         gCurrentControls.fMaxAccelCtl);
  541.     textBuffer[0] = length;
  542.     MoveTo(theXPos, theYPos );
  543.     DrawString((ConstStr255Param)textBuffer);
  544.     theYPos += 15;
  545.  
  546.     length = sprintf((char *)&textBuffer[1],
  547.         "%.2lf - Max. Velocity",
  548.         gCurrentControls.fMaxVelocityCtl);
  549.     textBuffer[0] = length;
  550.     MoveTo(theXPos, theYPos );
  551.     DrawString((ConstStr255Param)textBuffer);
  552.     
  553.     // Invalidate the rect so it wil draw
  554.     MarkRect(&invalRect);
  555.     
  556.     // Restore the color
  557.     RGBForeColor( &savedColor );
  558. }
  559.